package top.hekun.study.core.visitor.simple;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

import static org.objectweb.asm.Opcodes.*;
import static top.hekun.study.core.ClassSimpleModifyClassDemo.ERROR_CODE;

/**
 * 〈增加方法〉
 *
 * @author: Sakura
 * @date: 2023/5/8
 */
public class MyClassVisitor6 extends ClassVisitor {
    private boolean isMethodPresent;
    public MyClassVisitor6(int apiVersion, ClassVisitor classWriter) {
        super(apiVersion, classWriter);
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        System.out.println("MyClassVisitor6:visit");
        super.visit(version, access, name, signature, superName, interfaces);
    }
    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        System.out.println("MyClassVisitor6:visitField -- " + name);
        return super.visitField(access, name, descriptor, signature, value);
    }
    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        System.out.println("MyClassVisitor6:visitMethod -- " + name + " -- " + descriptor);
        if ("test4".equals(name)&& "(II)V".equals(descriptor)){
            isMethodPresent = true;
        }
        return super.visitMethod(access, name, descriptor, signature, exceptions);
    }
    @Override
    public void visitEnd() {
        System.out.println("MyClassVisitor6:visitEnd");
        if (!isMethodPresent) {
            // 添加方法
            // 根据方法调用顺序可知, visitMethod在visitEnd() 前调用
            MethodVisitor methodVisitor = super.visitMethod(ACC_PRIVATE , "test4", "(II)V", null, null);
            if (methodVisitor != null) {
                generateCode(methodVisitor);
            }
        }
        super.visitEnd();
    }

    /**
     * 编写方好体
     * @param methodVisitor
     */
    private void  generateCode(MethodVisitor methodVisitor){
        // 编写代码体
        methodVisitor.visitCode();
        methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
        methodVisitor.visitLdcInsn("手动添加的 V test4(II) 方法");
        methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
        // 检查出错误 缺少返回
        if (!ERROR_CODE) {
            methodVisitor.visitInsn(RETURN);
        }
        methodVisitor.visitMaxs(0,0);
        methodVisitor.visitEnd();
    }
}
